
module Barramento where

import Graphics.UI.GLUT

-- Lista com todos os nomes dos barramentos
todosBarramentos :: [String]
todosBarramentos = ["B", "MDRB", "PCB", "MBRB1", "MBRB2", "SPB", "LVB", "CPPB", "TOSB", "OPCB"
				   , "HULA", "ULADesl", "C", "CMAR", "CMDR", "CPC", "CSP", "CLV", "CCPP", "CTOS"
				   , "COPC", "CH", "atMDR", "atPC", "atMBR1", "atMBR2", "atSP", "atLV", "atCPP"
				   , "atTOS", "atOPC", "atResto", "MMIR", "attMAR", "attMDR", "attPC", "attSP"
				   , "attLV", "attCPP", "attTOS", "attOPC", "attH", "MBRend", "ULAN", "ULAZ"
				   , "NBIT", "ZBIT", "Addr", "J1", "J2", "MPCMem", "MPCFim", "MPCCab", "BDec"
				   , "MMem", "MUla", "MDesl", "MARMem", "MDRMem1", "MDRMem2", "PCMem", "MBRMem"
				   , "MMemF" ]

-- Desenha todos os Barramentos
desenhaTodos :: [String] -> IO ()
desenhaTodos [] = return ()
desenhaTodos (a:x) = do 
	desenhaBar (tipoBarramento a) False
	desenhaTodos x

-- Desenha a parte opaca dos barramentos
desenhaOpacos :: [String] -> GLdouble -> IO ()
desenhaOpacos [] _ = return ()
desenhaOpacos (a:x) porc = do
		desenhaOpacosAux (tipoBarramento a) ((soma (tipoBarramento a)) * porc)
		desenhaOpacos x porc
	where
		soma [] =  0
		soma ((Vector3 x y z, rotacao, tamanho, raio, seta):resto) = tamanho + soma resto

-- Desenha a parte opaca dos barramentos (auxiliar)
desenhaOpacosAux :: [(Vector3 GLfloat, String, GLdouble, GLdouble, String)] -> GLdouble -> IO ()
desenhaOpacosAux [] _ = return ()
desenhaOpacosAux ((Vector3 x y z, rotacao, tamanho, raio, seta):resto) valor =
	if (tamanho >= valor) then
			desenhaBar [(Vector3 x y z, rotacao, valor, raio, seta)] True
		else
			do
				desenhaBar [(Vector3 x y z, rotacao, tamanho, raio, seta)] True
				desenhaOpacosAux resto (valor - tamanho)

-- Make
makeBarramento :: Color4 GLfloat -> [String] -> [String] -> GLdouble -> IO DisplayList
makeBarramento cor cheios opacos porc = do
	[listaBar] <- genObjectNames 1
	defineList listaBar Compile $ do
		currentColor $= Color4 1 0 0 1
		materialAmbient Front $= Color4 1 0 0 1
		desenhaOpacos cheios 1
		if (porc > 0) then	desenhaOpacos opacos porc
			else do
				currentColor $= cor
				materialAmbient Front $= cor
		currentColor $= cor
		materialAmbient Front $= cor
		desenhaTodos todosBarramentos		
	shadeModel $= Flat
	return listaBar		

-- Desenha Barramento
desenhaBar :: [(Vector3 GLfloat, String, GLdouble, GLdouble, String)] -> Bool -> IO ()
desenhaBar [] _ = return ()
desenhaBar ((Vector3 x y z, rotacao, tamanho, raio, seta):resto) verm
	-- cima
	| rotacao == "C" = do
		preservingMatrix $ do			
			translate (Vector3 x y z :: Vector3 GLfloat)
			rotate ((-90) :: GLfloat) (Vector3 1 0 0)
			cilindro raio tamanho
			if (seta == ">") then cone (2 * raio) tamanho else return ()
		desenhaBar resto verm
	-- baixo
	| rotacao == "B" = do
		preservingMatrix $ do
			translate (Vector3 x y z :: Vector3 GLfloat)
			rotate (90 :: GLfloat) (Vector3 1 0 0)
			cilindro raio tamanho
			if (seta == ">") then cone (2 * raio) tamanho else return ()
		desenhaBar resto verm
	-- direita
	| rotacao == "D" = do
		preservingMatrix $ do
			translate (Vector3 x y z :: Vector3 GLfloat)
			rotate (90 :: GLfloat) (Vector3 0 1 0)	
			cilindro raio tamanho
			if (seta == ">") then cone (2 * raio) tamanho else return ()
		desenhaBar resto verm
	-- esquerda
	| rotacao == "E" = do
		preservingMatrix $ do			
			translate (Vector3 x y z :: Vector3 GLfloat)
			rotate ((-90) :: GLfloat) (Vector3 0 1 0)	
			cilindro raio tamanho
			if (seta == ">") then cone (2 * raio) tamanho else return ()
		desenhaBar resto verm
	-- tras
	| rotacao == "T" = do
		preservingMatrix $ do
			translate (Vector3 x y z :: Vector3 GLfloat)
			rotate (180 :: GLfloat) (Vector3 0 1 0)
			cilindro raio tamanho
			if (seta == ">") then cone (2 * raio) tamanho else return ()
		desenhaBar resto verm
	-- frente
	| otherwise 	 = do
		preservingMatrix $ do			
			translate (Vector3 x y z :: Vector3 GLfloat)			
			cilindro raio tamanho
			if (seta == ">") then cone (2 * raio) tamanho else return ()
		desenhaBar resto  verm
			where
				tam :: GLdouble -> GLdouble
				tam x = if verm then x + 0.01 else x
				-- Cilindro				
				cilindro :: GLdouble -> GLdouble -> IO ()
				cilindro x y = renderQuadric (QuadricStyle Nothing GenerateTextureCoordinates Inside FillStyle)
					  			(Cylinder (tam x) (tam x) y 15 1)
				-- Cone
				cone :: GLdouble -> GLdouble -> IO ()					  			
				cone x y = do
							translate (Vector3 0 0 y :: Vector3 GLdouble)
							renderQuadric (QuadricStyle Nothing GenerateTextureCoordinates Inside FillStyle)
								  (Cylinder (tam x) 0.1 3 15 1)
							translate (Vector3 0 0 (-y) :: Vector3 GLdouble)

-- Retorna a lista de coordenadas para desenho do barramento
tipoBarramento :: String -> [(Vector3 GLfloat, String, GLdouble, GLdouble, String)]
-- Barramento B
tipoBarramento "B" = [(Vector3 25 45 10, "B", 62, 1, ">")]
-- Registradores para Barramento B
	-- MDR
tipoBarramento "MDRB" = [(Vector3 (-20) 30 10, "D", 42, 0.5, ">")]
	-- PC
tipoBarramento "PCB" = [(Vector3 (-20) 20 10, "D", 42, 0.5, ">")]
	-- MBR
tipoBarramento "MBRB1" = [(Vector3 (-20) 10.5 10, "D", 42, 0.5, ">")]
tipoBarramento "MBRB2" = [(Vector3 (-20) 9 10, "D", 42, 0.5, ">")]
	-- SP
tipoBarramento "SPB" = [(Vector3 10 35 10, "D", 12, 0.5, ">")]
	-- LV
tipoBarramento "LVB" = [(Vector3 10 25 10, "D", 12, 0.5, ">")]
	-- CPP
tipoBarramento "CPPB" = [(Vector3 10 15 10, "D", 12, 0.5, ">")]
	-- TOS
tipoBarramento "TOSB" = [(Vector3 10 5 10, "D", 12, 0.5, ">")]
	-- OPC
tipoBarramento "OPCB" = [(Vector3 10 (-5) 10, "D", 12, 0.5, ">")]
-- H para ULA
tipoBarramento "HULA" = [(Vector3 10 (-15) 10, "D", 5.5, 1, "-"),
						 (Vector3 15 (-15) 10, "B", 2, 1, ">")]
-- ULA para Deslocador
tipoBarramento "ULADesl" = [(Vector3 20 (-30) 10, "B", 5.5, 1, "-"),
						    (Vector3 20 (-35) 10, "E", 7, 1, ">")]
-- Barramento C
tipoBarramento "C" = [(Vector3 (-10) (-35) 10, "E", 40.5, 1, "-"),
					  (Vector3 (-50) (-35) 10, "C", 77, 1, ">")]
-- Barramento C para Registradores
	-- MAR
tipoBarramento "CMAR" = [(Vector3 (-49) 40 10, "D", 7, 0.5, ">")]
	-- MDR
tipoBarramento "CMDR" = [(Vector3 (-49) 30 10, "D", 7, 0.5, ">")]
	-- PC
tipoBarramento "CPC" = [(Vector3 (-49) 20 10, "D", 7, 0.5, ">")]
	-- SP
tipoBarramento "CSP" = [(Vector3 (-49) 35 10, "D", 37, 0.5, ">")]
	-- LV
tipoBarramento "CLV" = [(Vector3 (-49) 25 10, "D", 37, 0.5, ">")]
	-- CPP
tipoBarramento "CCPP" = [(Vector3 (-49) 15 10, "D", 37, 0.5, ">")]
	-- TOS
tipoBarramento "CTOS" = [(Vector3 (-49) 5 10, "D", 37, 0.5, ">")]
	-- OPC
tipoBarramento "COPC" = [(Vector3 (-49) (-5) 10, "D", 37, 0.5, ">")]
	-- H
tipoBarramento "CH" = [(Vector3 (-49) (-15) 10, "D", 37, 0.5, ">")]
-- Ativadores das saidas para Barramento B (Decodificador 4-para-16)
	-- MDR
tipoBarramento "atMDR" = [(Vector3 12 42 (-7), "F", 4, 0.3, "-"),
						  (Vector3 12 42 (-3), "B", 12, 0.3, "-"),
						  (Vector3 12 30 (-3), "E", 30, 0.3, "-"),
						  (Vector3 (-18) 30 (-3), "F", 13, 0.3, "-")]
	-- PC
tipoBarramento "atPC" = [(Vector3 13 42 (-7), "F", 4, 0.3, "-"),
						 (Vector3 13 42 (-3), "B", 22, 0.3, "-"),
						 (Vector3 13 20 (-3), "E", 31, 0.3, "-"),
						 (Vector3 (-18) 20 (-3), "F", 13, 0.3, "-")]
	-- MBR
tipoBarramento "atMBR1" = [(Vector3 14 42 (-7), "F", 4, 0.3, "-"),
						   (Vector3 14 42 (-3), "B", 31.5, 0.3, "-"),
						   (Vector3 14 10.5 (-3), "E", 32, 0.3, "-"),
						   (Vector3 (-18) 10.5 (-3), "F", 13, 0.3, "-")]
tipoBarramento "atMBR2" = [(Vector3 15 42 (-7), "F", 4, 0.3, "-"),
						   (Vector3 15 42 (-3), "B", 33, 0.3, "-"),
						   (Vector3 15 9 (-3), "E", 33, 0.3, "-"),
						   (Vector3 (-18) 9 (-3), "F", 13, 0.3, "-")]						  
	-- SP
tipoBarramento "atSP" = [(Vector3 16 42 (-7), "F", 4, 0.3, "-"),
					     (Vector3 16 42 (-3), "B", 7, 0.3, "-"),
					     (Vector3 16 35 (-3), "F", 13, 0.3, "-")]
	-- LV
tipoBarramento "atLV" = [(Vector3 17 42 (-7), "F", 4, 0.3, "-"),
						 (Vector3 17 42 (-3), "B", 17, 0.3, "-"),
						 (Vector3 17 25 (-3), "F", 13, 0.3, "-")]
	-- CPP
tipoBarramento "atCPP" = [(Vector3 18 42 (-7), "F", 4, 0.3, "-"),
						  (Vector3 18 42 (-3), "B", 27, 0.3, "-"),
						  (Vector3 18 15 (-3), "F", 13, 0.3, "-")]
	-- TOS
tipoBarramento "atTOS" = [(Vector3 19 42 (-7), "F", 4, 0.3, "-"),
						  (Vector3 19 42 (-3), "B", 37, 0.3, "-"),
						  (Vector3 19 5 (-3), "F", 13, 0.3, "-")]
	-- OPC
tipoBarramento "atOPC" = [(Vector3 20 42 (-7), "F", 4, 0.3, "-"),
						  (Vector3 20 42 (-3), "B", 47, 0.3, "-"),
						  (Vector3 20 (-5) (-3), "F", 13, 0.3, "-")]
	-- Resto
tipoBarramento "atResto" = [(Vector3 21 42 (-7), "F", 2, 0.3, "-"),
							(Vector3 22 42 (-7), "F", 2, 0.3, "-"),
							(Vector3 23 42 (-7), "F", 2, 0.3, "-"),
							(Vector3 24 42 (-7), "F", 2, 0.3, "-"),
							(Vector3 25 42 (-7), "F", 2, 0.3, "-"),
							(Vector3 26 42 (-7), "F", 2, 0.3, "-"),
							(Vector3 27 42 (-7), "F", 2, 0.3, "-")]
-- Memoria para MIR
tipoBarramento "MMIR" = [(Vector3 (-20) 40 (-30), "F", 3, 1, ">")]
-- Ativadores das saidas do Barramento C para os registradores (Microinstrucao (C))
	-- MAR
tipoBarramento "attMAR" = [(Vector3 (-21) 40 (-20), "F", 10, 0.3, "-"),
						   (Vector3 (-21) 40 (-10), "E", 26, 0.3, "-"),
						   (Vector3 (-47) 40 (-10), "F", 20, 0.3, "-")]
	-- MDR
tipoBarramento "attMDR" = [(Vector3 (-19) 40 (-20), "F", 10, 0.3, "-"),
						  (Vector3 (-19) 40 (-10), "B", 10, 0.3, "-"),
						  (Vector3 (-19) 30 (-10), "E", 28, 0.3, "-"),						  
						  (Vector3 (-47) 30 (-10), "F", 20, 0.3, "-")]
	-- PC
tipoBarramento "attPC" = [(Vector3 (-17) 40 (-20), "F", 10, 0.3, "-"),
						  (Vector3 (-17) 40 (-10), "B", 20, 0.3, "-"),
						  (Vector3 (-17) 20 (-10), "E", 30, 0.3, "-"),
						  (Vector3 (-47) 20 (-10), "F", 20, 0.3, "-")]
	-- SP
tipoBarramento "attSP" = [(Vector3 (-20) 40 (-20), "F", 10, 0.3, "-"),
						  (Vector3 (-20) 40 (-10), "B", 5, 0.3, "-"),
						  (Vector3 (-20) 35 (-10), "E", 27, 0.3, "-"),
						  (Vector3 (-47) 35 (-10), "F", 20, 0.3, "-")]
	-- LV
tipoBarramento "attLV" = [(Vector3 (-18) 40 (-20), "F", 10, 0.3, "-"),
							 (Vector3 (-18) 40 (-10), "B", 15, 0.3, "-"),
							 (Vector3 (-18) 25 (-10), "E", 29, 0.3, "-"),
							 (Vector3 (-47) 25 (-10), "F", 20, 0.3, "-")]
	-- CPP
tipoBarramento "attCPP" = [(Vector3 (-16) 40 (-20), "F", 10, 0.3, "-"),
						   (Vector3 (-16) 40 (-10), "B", 25, 0.3, "-"),
						   (Vector3 (-16) 15 (-10), "E", 31, 0.3, "-"),
						   (Vector3 (-47) 15 (-10), "F", 20, 0.3, "-")]
	-- TOS
tipoBarramento "attTOS" = [(Vector3 (-15) 40 (-20), "F", 10, 0.3, "-"),
						   (Vector3 (-15) 40 (-10), "B", 35, 0.3, "-"),
						   (Vector3 (-15) 5 (-10), "E", 32, 0.3, "-"),
						   (Vector3 (-47) 5 (-10), "F", 20, 0.3, "-")]
	-- OPC
tipoBarramento "attOPC" = [(Vector3 (-14) 40 (-20), "F", 10, 0.3, "-"),
						   (Vector3 (-14) 40 (-10), "B", 45, 0.3, "-"),
						   (Vector3 (-14) (-5) (-10), "E", 33, 0.3, "-"),
						   (Vector3 (-47) (-5) (-10), "F", 20, 0.3, "-")]
	-- H
tipoBarramento "attH" = [(Vector3 (-13) 40 (-20), "F", 10, 0.3, "-"),
						 (Vector3 (-13) 40 (-10), "B", 55, 0.3, "-"),
						 (Vector3 (-13) (-15) (-10), "E", 34, 0.3, "-"),
						 (Vector3 (-47) (-15) (-10), "F", 20, 0.3, "-")]
-- MBR para calculador endereco
tipoBarramento "MBRend" = [(Vector3 (-21) 10 7, "T", 34, 0.3, "-"),
						   (Vector3 (-21) 10 (-27), "E", 24, 0.3, "-"),
						   (Vector3 (-45) 10 (-27), "C", 30, 0.3, "-"),
						   (Vector3 (-45) 40 (-27), "D", 1, 0.3, ">")]
-- Ula flip-flop (N)
tipoBarramento "ULAN" = [(Vector3 27 (-24) 10, "D", 13, 0.3, "-"),
						 (Vector3 40 (-24) 10, "T", 24, 0.3, "-"),
						 (Vector3 40 (-24) (-14), "C", 64, 0.3, "-"),
						 (Vector3 40 40 (-14), "E", 22, 0.3, "-"),
						 (Vector3 18 40 (-14), "T", 2, 0.3, ">")]
{-tipoBarramento "ULAN" = [(Vector3 18 (-25) 5, "T", 20, 0.3, "-"),
						 (Vector3 18 (-25) (-15), "C", 65, 0.3, "-"),
						 (Vector3 18 40 (-15), "T", 1, 0.3, ">")]-}
tipoBarramento "NBIT" = [(Vector3 18 40 (-21), "T", 2, 0.3, ">")]
-- Ula flip-flop (Z)
tipoBarramento "ULAZ" = [(Vector3 27 (-26) 10, "D", 13, 0.3, "-"),
						 (Vector3 40 (-26) 10, "T", 26, 0.3, "-"),
						 (Vector3 40 (-26) (-16), "C", 67, 0.3, "-"),
						 (Vector3 40 41 (-16), "E", 18, 0.3, "-"),
						 (Vector3 22 41 (-16), "T", 1, 0.3, ">")]
{-tipoBarramento "ULAZ" = [(Vector3 22 (-25) 5, "T", 20, 0.3, "-"),
						 (Vector3 22 (-25) (-15), "C", 65, 0.3, "-"),
						 (Vector3 22 40 (-15), "T", 1, 0.3, ">")]-}
tipoBarramento "ZBIT" = [(Vector3 22 40 (-21), "T", 2, 0.3, ">")]
-- Microinstrucao (Campo Addr)
tipoBarramento "Addr" = [(Vector3 (-31) 40 (-20), "F", 5, 0.3, "-"),
						 (Vector3 (-31) 40 (-15), "E", 9, 0.3, "-"),
						 (Vector3 (-40) 40 (-15), "T", 8, 0.3, ">")]
-- Microinstrucao (Campos J)
tipoBarramento "J1" = [(Vector3 (-27) 40 (-24), "T", 3, 0.3, "-"),
					   (Vector3 (-27) 40 (-27), "E", 9, 0.3, ">")]
tipoBarramento "J2" = [(Vector3 (-27) 40 (-20), "F", 3, 0.3, "-"),
					   (Vector3 (-27) 40 (-17), "B", 10, 0.3, "-"),
					   (Vector3 (-27) 30 (-17), "D", 37, 0.3, "-"),
					   (Vector3 10 30 (-17), "T", 11, 0.3, "-"),
					   (Vector3 10 30 (-28), "C", 10, 0.3, "-"),
					   (Vector3 10 40 (-28), "D", 3, 0.3, ">")]
-- MPC para Memoria
tipoBarramento "MPCMem" = [(Vector3 (-2) 40 (-37), "E", 3, 0.5, ">")]
-- Para MPC (bit inicial)
tipoBarramento "MPCCab" = [(Vector3 20 40 (-31), "T", 12, 0.3, "-"),
						   (Vector3 20 40 (-43), "E", 14, 0.3, "-"),
						   (Vector3 6 40 (-43), "F", 2, 0.3, ">")]
-- Para MPC (fim)
tipoBarramento "MPCFim" = [(Vector3 (-40) 40 (-28), "T", 15, 0.3, "-"),
						   (Vector3 (-40) 40 (-43), "D", 44, 0.3, "-"),
						   (Vector3 4 40 (-43), "F", 2, 0.3, ">")]
-- Mincroinstrucao (Campo B) para decodificador
tipoBarramento "BDec" = [(Vector3 (-9) 40 (-20), "F", 3, 0.3, "-"),
						 (Vector3 (-9) 40 (-17), "D", 23, 0.3, "-"),
						 (Vector3 14 40 (-17), "F", 1, 0.3, ">")]
-- Mincroinstrucao (Campo M) - sinais de memoria
tipoBarramento "MMem" = [(Vector3 (-11) 40 (-20), "F", 15, 0.3, "-"),
						 (Vector3 (-11) 40 (-5), "E", 19, 0.3, "-"),
						 (Vector3 (-30) 40 (-5), "F", 10, 0.3, ">")]
tipoBarramento "MMemF" = [(Vector3 (-11) 40 (-20), "F", 15, 0.3, "-"),
						  (Vector3 (-11) 40 (-5), "E", 19, 0.3, "-"),
						  (Vector3 (-30) 40 (-5), "B", 20, 0.3, "-"),
						  (Vector3 (-30) 20 (-5), "F", 10, 0.3, ">")]
-- Mincroinstrucao (Campo ULA) para Deslocador
tipoBarramento "MDesl" = [(Vector3 (-25) 40 (-20), "F", 7, 0.3, "-"),
						  (Vector3 (-25) 40 (-13), "B", 65, 0.3, "-"),
						  (Vector3 (-25) (-25) (-13), "F", 23, 0.3, "-"),
						  (Vector3 (-25) (-25) 10, "D", 35, 0.3, ">")]
-- Mincroinstrucao (Campo ULA) para ULA
tipoBarramento "MUla" = [(Vector3 (-23) 40 (-20), "F", 7, 0.3, "-"),
						 (Vector3 (-23) 40 (-13), "B", 67, 0.3, "-"),
						 (Vector3 (-23) (-27) (-13), "F", 23, 0.3, "-"),
						 (Vector3 (-23) (-27) 10, "D", 23, 0.3, "-"),
						 (Vector3 0 (-27) 10, "B", 3, 0.3, ">")]
-- Barramentos para a memoria
	-- MAR
tipoBarramento "MARMem" = [(Vector3 (-40) 38 8, "E", 15, 0.5, ">")]
	-- MDR
tipoBarramento "MDRMem1" = [(Vector3 (-40) 28 8, "E", 15, 0.5, ">")]
tipoBarramento "MDRMem2" = [(Vector3 (-58) 32 8, "D", 15, 0.5, ">")]
	-- PC
tipoBarramento "PCMem" = [(Vector3 (-40) 18 8, "E", 15, 0.5, ">")]
	-- MBR
tipoBarramento "MBRMem" = [(Vector3 (-58) 8 8, "D", 15, 0.5, ">")]

tipoBarramento _ = []